/**
 * @fileOverview Gear提供Javascript扩展
 * @author <a href="mailto:lexloo@126.com">lexloo</a>
 */
Gear.kernel.DefPlugIn('core/lang.js', function() {
	var toString = Object.prototype.toString,
		hasOwn = Object.prototype.hasOwnProperty,
		push = Array.prototype.push,
		slice = Array.prototype.slice,
		trim = String.prototype.trim,
		indexOf = Array.prototype.indexOf,	
		lowerCase = String.prototype.toString,

		// JSON 正则表达式
		rvalidchars = /^[\],:{}\s]*$/,
		rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
		rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
		rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,

		// 裁剪字符串
		trimLeft = /^\s+/,
		trimRight = /\s+$/;
	
	$Lang = Gear.lang = {
		/**
		 * 判断对象是否为指定类型,支持如下类型的判断:1、Null<br/> 2、Undifined<br/> 3、Number<br/>
		 * 4、String<br/> 5、Boolean<br/> 6、Object<br/> 7、Array<br/> 8、Regexp<br/>
		 * 9、Date<br/> 10、Function<br/>
		 */
		is : function(o, type) {
			var type = lowerCase.call(type);

			return (type == 'null' && o === null) || 
				 	(type == typeof o) || 
				 	(type == 'object' && o === Object(o)) || 
				 	(type == 'number' && isFinite(o)) || 
				 	(Array.isArray(o)) || 
				 	toString.call(o).slice(8, -1).toLowerCase() == type;
		},

		/**
		 * 判断对象是否为值(Value)
		 * 
		 * @public
		 * @since 1.0
		 * @param o {Object} 判断的对象
		 * @return {Boolean} 如果不为 null/undefined/NaN || false 时为真
		 */
		isValue : function(o) {
			return ($Lang.is(o, 'object') || $Lang.is(o, 'string') || $Lang.is(o, 'number') || $Lang.is(o, 'boolean'));
		},
		/**
		 * 对象属性复制
		 * 
		 * @public
		 * @since 1.0
		 * @param {Object} obj 属性接收者
		 * @param {Object} config 属性提供值者
		 * @param {Object} [defaults] 默认属性提供者
		 * @return {Object} 对象
		 */
		apply : function(o, c, defaults) {
			if (defaults) {
				$Lang.apply(o, defaults);
			}

			if (o && c && $Lang.isObject(c)) {
				for ( var p in c) {
					o[p] = c[p];
				}
			}
		},

		/*
		 * IE will not enumerate native functions in a derived object even if
		 * the function was overridden. This is a workaround for specific
		 * functions we care about on the Object prototype. @param {Function} r
		 * the object to receive the augmentation @param {Function} s the object
		 * that supplies the properties to augment @private
		 */
		/*
		 * __IEEnumFix: function(r, s) { if (org.antlr.env.ua.ie) { var
		 * add=["toString", "valueOf"], i; for (i=0;i<add.length;i=i+1) { var
		 * fname=add[i],f=s[fname]; if (org.antlr.lang.isFunction(f) &&
		 * f!=Object.prototype[fname]) { r[fname]=f; } } } },
		 */
		/**
		 * 建立继承机制,包括原型、构造器、超类属性，静态对象不继承
		 * 
		 * @public
		 * @since 1.0
		 * @param {Function} subc 子类
		 * @param {Function} superc 父类
		 * @param {Object} [overrides] 其它属性/方法,覆盖超类提供的属性/方法。
		 */
		extend : function(subc, superc, overrides) {
			if (!superc || !subc) {
				throw new Error("$Lang.extend 失败, 请检查包括所有依赖。");
			}
			var F = function() {
			};
			F.prototype = superc.prototype;
			subc.prototype = new F();
			subc.prototype.constructor = subc;
			subc.superclass = superc.prototype;
			if (superc.prototype.constructor == Object.prototype.constructor) {
				superc.prototype.constructor = superc;
			}

			if (overrides) {
				for ( var i  in overrides) {
					subc.prototype[i] = overrides[i];
				}

				/* IE 可能不会复制toString， valueOf相关函数 */
				/*
				 * com.priorbi.lang._IEEnumFix(subc.prototype, overrides);
				 */
			}
		},
		
		/**
		 * 函数备忘模式
		 * @param {Function} fn 函数
		 * @param {Object} scope 上下文
		 * @param {Function} postProcesssor 取值后处理
		 */
	    memoize : function(fn, scope, postprocessor) {
	        function newf() {
	            var arg = Array.prototype.slice.call(arguments, 0),
	                args = arg.join(","),
	                cache = newf.cache = newf.cache || {},
	                count = newf.count = newf.count || [];
	                
	            if (cache.hasOwnProperty(args)) {
	                return postprocessor ? postprocessor(cache[args]) : cache[args];
	            }
	            
	            /* LILO 保存1000个缓存值*/
	            count.length >= 1e3 && delete cache[count.shift()];
	            count.push(args);
	            cache[args] = fn.apply(scope, arg);
	            
	            return postprocessor ? postprocessor(cache[args]) : cache[args];
	        }
	        
	        return newf;
	    }
	};

	/* 扩充函数 */
	// 裁剪字符串
	String.trim = trim ?
		function(text) {
			return text == null ? '': trim.call(text);
		} 
		:
		function(text) {
			return text == null ? '': text.toString().replace(trimLeft, '').replace(trimRight, '');
		};

	/**
	 * 可迭代数据转化为数组
	 * 
	 * @since 1.0
	 * @param {Object} o 可迭代数据
	 */
	$A = function(o) {
		if (!o) {
			return [];
		}

		if (o.toArray) {
			return o.toArray();
		}

		var length = o.length, results = new Array(length);
		while (length--) {
			results[length] = o[length];
		}

		return results;
	};

	/* Array扩充 */
	/**
	 * 删除数组指定位置的元素
	 * 
	 * @since 1.0
	 * @param {Number} index 位置
	 */
	Array.prototype.remove = function(index) {
		if (isNaN(index) || index > this.length) {
			return false;
		}
		this.splice(index, 1);
	};

	/**
	 * 删除最后一个元素
	 * 
	 * @since 1.0
	 */
	Array.prototype.removeLast = function() {
		this.remove(this.length - 1);
	};

	/**
	 * 判断Array是否包含指定对象
	 * 
	 * @since 1.0
	 * @param {Object} o 目标对象
	 * @returns {Boolean} 如果包含目标对象则为true，否则为false
	 */
	Array.prototype.contains = function(o) {
		return this.indexOf(o) > -1;
	};

	/**
	 * 清空Array
	 * 
	 * @since 1.0
	 * @return 当前数组
	 */
	Array.prototype.clear = function() {
		this.length = 0;
		return this;
	};

	/**
	 * Array对象不包含元素
	 * 
	 * @since 1.0
	 * @returns 不包含元素时为true，否则为false
	 */
	Array.prototype.isEmpty = function() {
		return 0 == this.length;
	};

	/**
	 * 返回最后Array的最后一个元素
	 */
	Array.prototype.getLast = function() {
		if (this.isEmpty()) {
			return null;
		} else {
			return this[this.length - 1];
		}
	};

	/**
	 * 对象转换成字符串,如果为null或undefined则转换为空
	 * 
	 * @since 1.0
	 * @param {Object}o 对象
	 * @returns 字符串
	 */
	String.convert = function(o) {
		var defValue = arguments[1] ? arguments[1] : '';

		if (o == null || o == undefined) {
			return defValue;
		} else {
			if (o.toString) {
				return o.toString();
			} else {
				return defValue;
			}
		}
	};

	/* String 扩充 */
	/**
	 * 字符串驼峰表示
	 * 
	 * @returns {String} 字符串驼峰表示
	 */
	String.prototype.camelize = function() {
		var parts = this.split('-'), len = parts.length;
		if (len == 1)
			return parts[0];

		var camelized = this.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0];

		for ( var i = 1; i < len; i++)
			camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

		return camelized;
	};

	/**
	 * 字符串首字母大写，其余小写
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.capitalize = function() {
		return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
	};

	/**
	 * 清除字符串两端空格
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.trim = function() {
		return this.replace(/(^\s*)|(\s*$)/g, "");
	};

	/**
	 * 清除字符串左端空格
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.ltrim = function() {
		return this.replace(/(^\s*)/g, "");
	};

	/**
	 * 清除字符串右端空格
	 * 
	 * @returns {String} 字符串
	 */
	String.prototype.rtrim = function() {
		return this.replace(/(\s*$)/g, "");
	};

	/**
	 * 判断字符串是否包含子串
	 * 
	 * @param {String} text 子串
	 * @returns {Boolean} 如果包含则为true，否则为false
	 */
	String.prototype.include = function(pattern) {
		return this.indexOf(pattern) > -1;
	};

	/**
	 * 判断字符串是否以指定字符串开始
	 * 
	 * @param pattern 指定字符串
	 * @returns {Boolean} 以指定字符串开始则为true，否则为false
	 */
	String.prototype.startsWith = function(pattern) {
		return this.indexOf(pattern) === 0;
	};

	/**
	 * 判断字符串是否以指定字符串结束
	 * 
	 * @param pattern 指定字符串
	 * @returns {Boolean} 以指定字符串结束则为true，否则为false
	 */
	String.prototype.endsWith = function(pattern) {
		var d = this.length - pattern.length;
		return d >= 0 && this.lastIndexOf(pattern) === d;
	};

	/**
	 * 判断字符串是否为空
	 * 
	 * @returns {Booelan} 如果为空则为true，否则为false
	 */
	String.prototype.isEmpty = function() {
		return this == '';
	};

	/**
	 * 替换所有子串
	 * 
	 * @param findText 查找字符串
	 * @param repText 替换的字符串
	 * @return {String} 替换后的字符串
	 */
	String.prototype.replaceAll = function(findText, repText) {
		return this.replace(new RegExp(findText, 'gm'), repText);
	};

	/**
	 * 格式化字符串
	 * 
	 * @example 'hello, My name is {0} {1}.'.format(firstName, lastName);
	 * @return {String} 格式化后的字符串
	 */
	String.prototype.format = function() {
		if (arguments.length == 0) {
			return this;
		} else {
			var str = this;
			for ( var i = 0; i < arguments.length; i++) {
				str = str.replaceAll('\\{' + i + '\\}', arguments[i]);
			}

			return str;
		}
	};

	/**
	 * 以逗号分隔的字符串转化为数组
	 * 
	 * @return {Array} 数组
	 */
	String.prototype.toArray = function() {
		return this.split(',');
	};

	/**
	 * 过滤Tags
	 * 
	 * @return {String} 字符串
	 */
	String.prototype.stripTags = function() {
		return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
	};

	/**
	 * 替换HTML符号
	 * 
	 * @return {String} 字符串
	 */
	String.prototype.escapeHTML = function() {
		return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
	};

	/**
	 * 恢复HTML符号
	 * 
	 * @return {String} 字符串
	 */
	String.prototype.unescapeHTML = function() {
		return this.stripTags().replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&').replace(/&quot;/g,
				'"');
	};

	/* 扩充Function功能 */
	/**
	 * 绑定函数到上下文环境
	 * 
	 * @since 1.0
	 * @returns {Function} 函数
	 */
	Function.prototype.bind = function() {
		if (arguments.length < 2 && arguments[0] === undefined)
			return this;
		var __method = this, args = $A(arguments), object = args.shift();
		return function() {
			return __method.apply(object, args.concat($A(arguments)));
		};
	};

	/**
	 * 绑定函数到事件监听
	 * 
	 * @since 1.0
	 * @returns {Function} 函数
	 */
	Function.prototype.bindAsEventListener = function() {
		var __method = this, args = $A(arguments), object = args.shift();
		return function(event) {
			return __method.apply(object, [ event || window.event ].concat(args));
		};
	};

	/**
	 * 创建拦截器
	 */
	Function.prototype.createInterceptor = function(fcn, scope) {
		var method = this;
		return !$Lang.isFunction(fcn) ? this : function() {
			var me = this, args = arguments;
			return (fcn.apply(scope || me || window, args) !== false) ? method.apply(me || window, args) : null;
		};
	};
});